home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / sys / sysCalls.c < prev    next >
C/C++ Source or Header  |  1991-06-27  |  29KB  |  1,173 lines

  1. /* 
  2.  * sysCalls.c --
  3.  *
  4.  *    Miscellaneous system calls that are lumped under the Sys_ prefix.
  5.  *
  6.  * Copyright 1986 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /sprite/src/kernel/sys/RCS/sysCalls.c,v 9.41 91/06/27 12:13:00 mgbaker Exp $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14.  
  15. #include <sprite.h>
  16. #include <mach.h>
  17. #include <sys.h>
  18. #include <sysInt.h>
  19. #include <sysStats.h>
  20. #include <time.h>
  21. #include <timer.h>
  22. #include <traceLog.h>
  23. #include <vm.h>
  24. #include <machMon.h>
  25. #include <proc.h>
  26. #include <dbg.h>
  27. #include <fs.h>
  28. #include <fsutil.h>
  29. #include <fsprefix.h>
  30. #include <rpc.h>
  31. #include <net.h>
  32. #include <sched.h>
  33. #include <dev.h>
  34. #include <recov.h>
  35. #include <procMigrate.h>
  36. #include <string.h>
  37. #include <stdio.h>
  38. #include <main.h>
  39. #ifdef sun4
  40. #include <vmMach.h>
  41. #endif
  42. #ifdef sun4c
  43. #include <devSCSIC90.h>
  44. #endif sun4c
  45. #ifdef SOSP91
  46. #include <fsStat.h>
  47. #include <sospRecord.h>
  48. #include <fscache.h>
  49. #endif SOSP91
  50.  
  51. Boolean    sys_ErrorShutdown = FALSE;
  52. Boolean    sys_ShuttingDown = FALSE;
  53.  
  54. #ifdef SOSP91
  55. TraceLog_Header *SOSP91TracePtr = NULL;
  56. extern Boolean traceLog_Disable;
  57.  
  58. /* Ken's statistics. */
  59. extern Timer_Ticks nameTime[], totalNameTime;
  60. extern int SOSPLookupNum, SOSPLookupComponent, SOSPLookupPrefixComponent;
  61. #endif
  62.  
  63.  
  64. /*
  65.  *----------------------------------------------------------------------
  66.  *
  67.  * Sys_GetTimeOfDay --
  68.  *
  69.  *    Returns the current system time to a local user process.
  70.  *    If any argument is USER_NIL, that value is not returned.
  71.  *
  72.  *    The "real" time of day is returned, rather than the software
  73.  *    time.
  74.  *
  75.  * Results:
  76.  *    SUCCESS         The call was successful.
  77.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  78.  *
  79.  * Side effects:
  80.  *    None.
  81.  *
  82.  *----------------------------------------------------------------------
  83.  */
  84.  
  85. ReturnStatus
  86. Sys_GetTimeOfDay(timePtr, localOffsetPtr, DSTPtr)
  87.     Time    *timePtr;        /* Buffer to store the UT time. */
  88.     int        *localOffsetPtr;    /* Buffer to store the number of minutes
  89.                      * from UT (a negative value means you 
  90.                      * are west of the Prime Meridian. */
  91.     Boolean    *DSTPtr;        /* Buffer to store a flag that's TRUE
  92.                      * if DST is followed. */
  93. {
  94.     Time    curTime;
  95.     int        curLocalOffset;
  96.     Boolean    curDST;
  97.  
  98.     Timer_GetRealTimeOfDay(&curTime, &curLocalOffset, &curDST);
  99.  
  100.     if (timePtr != USER_NIL) {
  101.     if (Proc_ByteCopy(FALSE, sizeof(Time),
  102.           (Address) &curTime, (Address) timePtr) != SUCCESS) {
  103.         return(SYS_ARG_NOACCESS);
  104.     }
  105.     }
  106.     if (localOffsetPtr != USER_NIL) {
  107.     if (Proc_ByteCopy(FALSE, sizeof(int),(Address) &curLocalOffset, 
  108.                 (Address) localOffsetPtr) != SUCCESS) {
  109.         return(SYS_ARG_NOACCESS);
  110.     }
  111.     }
  112.     if (DSTPtr != USER_NIL) {
  113.     if (Proc_ByteCopy(FALSE, sizeof(Boolean),(Address) &curDST,
  114.                     (Address) DSTPtr) != SUCCESS) {
  115.         return(SYS_ARG_NOACCESS);
  116.     }
  117.     }
  118.     return(SUCCESS);
  119. }
  120.  
  121. /*
  122.  *----------------------------------------------------------------------
  123.  *
  124.  * Sys_SetTimeOfDay --
  125.  *
  126.  *    Changes the current system time to the value specified by
  127.  *    the arguments. The timePtr argument  must be valid.
  128.  *
  129.  * Results:
  130.  *    SUCCESS         The call was successful.
  131.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  132.  *
  133.  * Side effects:
  134.  *    The system time is updated to a new value.
  135.  *
  136.  *----------------------------------------------------------------------
  137.  */
  138.  
  139. ReturnStatus
  140. Sys_SetTimeOfDay(timePtr, localOffset, DST)
  141.     Time    *timePtr;    /* New value for the UT (GMT) time. */
  142.     int        localOffset;    /* new value for the offset in minutes 
  143.                  * from UT.*/
  144.     Boolean    DST;        /* If TRUE, DST is used at this site. */
  145. {
  146.     Time    newTime;
  147.  
  148.     if (timePtr == USER_NIL || 
  149.         (Proc_ByteCopy(TRUE, sizeof(Time), (Address) timePtr, 
  150.             (Address) &newTime) != SUCCESS)) {
  151.     return(SYS_ARG_NOACCESS);
  152.     }
  153.     Timer_SetTimeOfDay(newTime, localOffset, DST);
  154.     return(SUCCESS);
  155. }
  156.  
  157.  
  158. /*
  159.  *----------------------------------------------------------------------
  160.  *
  161.  * Sys_DoNothing --
  162.  *
  163.  *    This system call simply returns SUCCESS. It does not perform any
  164.  *    function.
  165.  *
  166.  * Results:
  167.  *    SUCCESS         This value is always returned.
  168.  *
  169.  * Side effects:
  170.  *    None.
  171.  *
  172.  *----------------------------------------------------------------------
  173.  */
  174.  
  175. ReturnStatus
  176. Sys_DoNothing()
  177. {
  178.     Sched_ContextSwitch(PROC_READY);
  179.     return(SUCCESS);
  180. }
  181.  
  182.  
  183. #define    MAX_WAIT_INTERVALS    3
  184. Boolean    shutdownDebug = FALSE;
  185.  
  186. /*
  187.  *----------------------------------------------------------------------
  188.  *
  189.  * Sys_Shutdown --
  190.  *
  191.  *    This system call calls appropriate routines to shutdown
  192.  *    the system in an orderly fashion.
  193.  *
  194.  * Results:
  195.  *    SUCCESS     This value is always returned.
  196.  *    SYS_ARG_NOACESS    The reboot string was inaccessible.    
  197.  *
  198.  * Side effects:
  199.  *    None.
  200.  *
  201.  *----------------------------------------------------------------------
  202.  */
  203.  
  204. ReturnStatus
  205. Sys_Shutdown(flags, rebootString)
  206.     int        flags;
  207.     char    *rebootString;
  208. {
  209.     Time        waitTime;
  210.     int            alive;
  211.     int            timesWaited;
  212.     Boolean        userDead = FALSE;
  213.     char        string[100];
  214.     int            accLength;
  215.     int            strLength;
  216.     ReturnStatus    status;
  217.     Proc_ControlBlock    *procPtr;
  218.  
  219.  
  220.     if (flags & SYS_REBOOT) {
  221.     if (rebootString == (char *) USER_NIL) {
  222.         string[0] = '\0';
  223.     } else {
  224.         status = Proc_MakeStringAccessible(100, &rebootString, &accLength,
  225.                             &strLength);
  226.         if (status != SUCCESS) {
  227.         return(SYS_ARG_NOACCESS);
  228.         }
  229.         (void) strcpy(string, rebootString);
  230.         Proc_MakeUnaccessible(rebootString, accLength);
  231.     }
  232.     }
  233.  
  234.     if (flags & SYS_DEBUG) {
  235.     sys_ErrorShutdown = TRUE;
  236.     }
  237.  
  238.     if (flags & SYS_KILL_PROCESSES) {
  239.     if (flags & SYS_WRITE_BACK) { 
  240.         /*
  241.          * Do a few initial syncs.
  242.          * These are necessary because the cache isn't getting written
  243.          * out properly with the new block cleaner.
  244.          */
  245.         printf("Doing initial syncs\n");
  246.         Fsutil_Sync(-1, 0);
  247.         Fsutil_Sync(-1, 0);
  248.         Fsutil_Sync(-1, 0);
  249.         printf("Done initial syncs\n");
  250.     }
  251.     /*
  252.      * Turn ourselves into a kernel process since we no longer need
  253.      * user process resources.
  254.      */
  255.     procPtr = Proc_GetCurrentProc();
  256.     Proc_Lock(procPtr);
  257. #ifdef sun4
  258.     /*
  259.      * Flush the virt addresses cache on the sun4 before turning ourselves
  260.      * into a kernel process. If we don't do this we will get cache
  261.      * write-back errors from dirty cache blocks of the shutdown program.
  262.      */
  263.     Mach_FlushWindowsToStack();
  264.     VmMach_FlushCurrentContext();
  265. #endif
  266.     procPtr->genFlags &= ~PROC_USER;
  267.     procPtr->genFlags |= PROC_KERNEL;
  268.     Proc_Unlock(procPtr);
  269.     VmMach_ReinitContext(procPtr);
  270.  
  271.     /*
  272.      * Get rid of any migrated processes.
  273.      */
  274.     (void) Proc_EvictForeignProcs();
  275.     
  276.     waitTime.seconds = 5;
  277.     waitTime.microseconds = 0;
  278.     while (TRUE) {
  279.         if (userDead) {
  280.         sys_ShuttingDown = TRUE;
  281.         }
  282.         timesWaited = 0;
  283.         while (TRUE) {
  284.         alive = Proc_KillAllProcesses(!userDead);
  285.         if (alive == 0) {
  286.             break;
  287.         }
  288.         if (timesWaited >= MAX_WAIT_INTERVALS) {
  289.             printf("%d %s processes still alive.\n", alive,
  290.                 userDead ? "kernel" : "user");
  291.             break;
  292.         }
  293.         timesWaited++;
  294.         printf("Waiting with %d %s processes still alive\n", alive,
  295.                 userDead ? "kernel" : "user");
  296.         if (shutdownDebug) {
  297.             DBG_CALL;
  298.         }
  299.         (void) Sync_WaitTime(waitTime);
  300.         }
  301.         if (userDead) {
  302.         break;
  303.         }
  304.         userDead = TRUE;
  305.     }
  306.     /*
  307.      * Give this process highest priority so that no other process 
  308.      * can interrupt it.
  309.      */
  310.     (void) Proc_SetPriority(PROC_MY_PID, PROC_NO_INTR_PRIORITY, FALSE);
  311.     }
  312.  
  313.     /*
  314.      * Sync the disks.
  315.      */
  316.     if (flags & SYS_WRITE_BACK) {
  317.     printf("Syncing disks\n");
  318.     Fsutil_Sync(-1, flags & SYS_KILL_PROCESSES);
  319.     }
  320.  
  321.     if (flags & SYS_HALT) {
  322.     Mach_MonAbort();
  323.     } else if (flags & SYS_REBOOT) {
  324.     Mach_MonReboot(string);
  325.     } else if (flags & SYS_DEBUG) {
  326.     sys_ShuttingDown = FALSE;
  327.     sys_ErrorShutdown = FALSE;
  328.     DBG_CALL;
  329.     }
  330.  
  331.     return(SUCCESS);
  332. }
  333.  
  334. Boolean    sys_ShouldSyncDisks = TRUE;
  335.  
  336. /*
  337.  *----------------------------------------------------------------------
  338.  *
  339.  * Sys_SyncDisks --
  340.  *
  341.  *    This routine is called when the system encountered an error and
  342.  *    the disks should be synced.
  343.  *
  344.  * Results:
  345.  *    None.
  346.  *
  347.  * Side effects:
  348.  *    None.
  349.  *
  350.  *----------------------------------------------------------------------
  351.  */
  352.  
  353. /*
  354.  * Exported so we can deny RPC requests as we die.
  355.  * Otherwise we can hang RPCs if we hang trying to sync our disks.
  356.  */
  357. Boolean    sys_ErrorSync = FALSE;
  358.  
  359.  
  360. void
  361. Sys_SyncDisks(trapType)
  362.     int    trapType;
  363. {
  364.     char    *SpriteVersion();
  365.     
  366.     if (sys_ErrorSync) {
  367.     printf("Error type %d while syncing disks.\n", trapType);
  368.     sys_ShouldSyncDisks = FALSE;
  369.     sys_ErrorSync = FALSE;
  370.     DBG_CALL;
  371.     return;
  372.     }
  373.     if (sys_ShouldSyncDisks && !mach_AtInterruptLevel && !sys_ShuttingDown &&
  374.         !dbg_BeingDebugged && (trapType != MACH_BRKPT_TRAP || sysPanicing)) {
  375.     printf("Syncing disks.  Version: %s\n", SpriteVersion());
  376.     sys_ErrorSync = TRUE;
  377.     Fsutil_Sync(-1, TRUE);
  378.     sys_ErrorSync = FALSE;
  379.     }
  380. }
  381.  
  382.  
  383. /*
  384.  *----------------------------------------------------------------------
  385.  *
  386.  * Sys_GetMachineInfo --
  387.  *
  388.  *    Returns the machine architecture and type information.
  389.  *
  390.  * Results:
  391.  *    SUCCESS         The call was successful.
  392.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  393.  *
  394.  * Side effects:
  395.  *    None.
  396.  *
  397.  *----------------------------------------------------------------------
  398.  */
  399.  
  400. ReturnStatus
  401. Sys_GetMachineInfo(archPtr, typePtr, clientIDPtr)
  402.     int    *archPtr;    /* Buffer to hold machine architecture #. */
  403.     int    *typePtr;    /* Buffer to hold machine type. */
  404.     int    *clientIDPtr;    /* Buffer to hold client ID. */
  405. {
  406.  
  407.     if (archPtr != (int *) USER_NIL) {
  408.     int arch = Mach_GetMachineArch();
  409.  
  410.     if (Proc_ByteCopy(FALSE, sizeof(int), (Address) &arch, 
  411.                 (Address) archPtr) != SUCCESS) {
  412.         return(SYS_ARG_NOACCESS);
  413.     }
  414.     }
  415.  
  416.     if (typePtr != (int *) USER_NIL) {
  417.  
  418.     int type = Mach_GetMachineType();
  419.  
  420.     if (Proc_ByteCopy(FALSE, sizeof(int), (Address) &type, 
  421.                 (Address) typePtr) != SUCCESS) {
  422.         return(SYS_ARG_NOACCESS);
  423.     }
  424.     }
  425.  
  426.  
  427.     if (clientIDPtr != (int *) USER_NIL) {
  428.     if (Proc_ByteCopy(FALSE, sizeof(int), (Address) &rpc_SpriteID, 
  429.                 (Address) clientIDPtr) != SUCCESS) {
  430.         return(SYS_ARG_NOACCESS);
  431.     }
  432.     }
  433.  
  434.     return(SUCCESS);
  435. }
  436. /*
  437.  *----------------------------------------------------------------------
  438.  *
  439.  * Sys_GetMachineInfoNew --
  440.  *
  441.  *    Returns the machine information..
  442.  *
  443.  * Results:
  444.  *    SUCCESS         The call was successful.
  445.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  446.  *
  447.  * Side effects:
  448.  *    None.
  449.  *
  450.  *----------------------------------------------------------------------
  451.  */
  452.  
  453. ReturnStatus
  454. Sys_GetMachineInfoNew(infoSize, infoBufPtr)
  455.     int            infoSize;    /* Size of the info structure. */
  456.     Address         infoBufPtr;    /* Info structure to fill in */
  457. {
  458.     Sys_MachineInfo    info;
  459.     int            bytesToCopy;
  460.  
  461.     if (infoSize < sizeof(Sys_MachineInfo)) {
  462.     bytesToCopy = infoSize;
  463.     } else {
  464.     bytesToCopy = sizeof(Sys_MachineInfo);
  465.     }
  466.     info.architecture = Mach_GetMachineArch();
  467.     info.type = Mach_GetMachineType();
  468.     info.processors = Mach_GetNumProcessors();
  469.     if (Vm_CopyOut(bytesToCopy, (Address) &info, infoBufPtr) != SUCCESS) {
  470.     return(SYS_ARG_NOACCESS);
  471.     }
  472.     return(SUCCESS);
  473. }
  474.  
  475.  
  476. /*
  477.  *----------------------------------------------------------------------
  478.  *
  479.  * Sys_StatsStub --
  480.  *
  481.  *    System call stub for the Statistics hook.
  482.  *
  483.  * Results:
  484.  *    SUCCESS            - the data were returned.
  485.  *    GEN_INVALID_ARG        - if a bad argument was passed in.
  486.  *    ?            - result from Vm_CopyOut.
  487.  *    
  488.  *
  489.  * Side effects:
  490.  *    Fill in the requested statistics.
  491.  *
  492.  *----------------------------------------------------------------------
  493.  */
  494. ReturnStatus
  495. Sys_StatsStub(command, option, argPtr)
  496.     int command;        /* Specifies what to do */
  497.     int option;            /* Modifier for command */
  498.     Address argPtr;        /* Argument for command */
  499. {
  500.     /*
  501.      * These extern decl's are temporary and should be removed when the
  502.      * START_STATS and END_STATS are removed.
  503.      */
  504.     extern void    Dev_StartIOStats();
  505.     extern void    Dev_StopIOStats();
  506.     extern void    Sched_StopSchedStats();
  507.     extern void    Sched_StartSchedStats();
  508.  
  509.     ReturnStatus status = SUCCESS;
  510.     
  511.     switch(command) {
  512.     case SYS_GET_VERSION_STRING: {
  513.         /*
  514.          * option is the length of the storage referenced by argPtr.
  515.          */
  516.         register int length;
  517.         register char *version;
  518.         version = (char *)SpriteVersion();
  519.         length = strlen(version) + 1;
  520.         if (option <= 0) {
  521.         status = GEN_INVALID_ARG;
  522.         break;
  523.         }
  524.         if (option < length) {
  525.         length = option;
  526.         }
  527.         status = Vm_CopyOut(length, version, argPtr);
  528.         break;
  529.     }
  530.     case SYS_SYNC_STATS: {
  531.         register Sync_Instrument *syncStatPtr;
  532.  
  533.         syncStatPtr = (Sync_Instrument *)argPtr;
  534.         if (syncStatPtr == (Sync_Instrument *)NIL ||
  535.         syncStatPtr == (Sync_Instrument *)0 ||
  536.         syncStatPtr == (Sync_Instrument *)USER_NIL) {
  537.         
  538.         Sync_PrintStat();
  539.         } else if (option <= 0) {
  540.         status = GEN_INVALID_ARG;
  541.         break;
  542.         } else {
  543.         if (option > sizeof(sync_Instrument)) {
  544.             option = sizeof(sync_Instrument);
  545.         }
  546.         status = Vm_CopyOut(option,
  547.                   (Address) sync_Instrument,
  548.                   (Address) syncStatPtr);
  549.         }
  550.         break;
  551.     }
  552.     case SYS_VM_STATS: {
  553.         if (argPtr == (Address)NIL ||
  554.         argPtr == (Address)0 ||
  555.         argPtr == (Address)USER_NIL) {
  556.         return(GEN_INVALID_ARG);
  557.         } else {
  558.         status = Vm_CopyOut(sizeof(Vm_Stat), (Address)&vmStat, argPtr);
  559.         }
  560.         break;
  561.     }
  562. #ifdef SOSP91
  563.     case SYS_SCHED_MORE_STATS: {
  564.         Sys_SchedOverallTimes *schedOverallPtr;
  565.         Sys_SchedOverallTimes schedOverall;
  566.  
  567.         schedOverallPtr = (Sys_SchedOverallTimes *)argPtr;
  568.         if (schedOverallPtr == (Sys_SchedOverallTimes *)NIL ||
  569.             schedOverallPtr == (Sys_SchedOverallTimes *)0 ||
  570.             schedOverallPtr == (Sys_SchedOverallTimes *)USER_NIL) {
  571.         status = GEN_INVALID_ARG;
  572.         } else if (option < sizeof (Sys_SchedOverallTimes)) {
  573.         status = GEN_INVALID_ARG;
  574.         } else {
  575.         Timer_TicksToTime(sched_OverallTimesPerProcessor[0].kernelTime,
  576.             &schedOverall.kernelTime);
  577.         Timer_TicksToTime(sched_OverallTimesPerProcessor[0].userTime,
  578.                 &schedOverall.userTime);
  579.         Timer_TicksToTime(
  580.             sched_OverallTimesPerProcessor[0].userTimeMigrated,
  581.             &schedOverall.userTimeMigrated);
  582.         status = Vm_CopyOut(sizeof(Sys_SchedOverallTimes),
  583.             (Address)&schedOverall, argPtr);
  584.         }
  585.         break;
  586.     }
  587.     case SYS_FS_SOSP_MIG_STATS: {
  588.         Fs_SospMigStats    *statsPtr;
  589.  
  590.         statsPtr = (Fs_SospMigStats *) argPtr;
  591.         if (statsPtr == (Fs_SospMigStats *)NIL ||
  592.             statsPtr == (Fs_SospMigStats *) 0 ||
  593.             statsPtr == (Fs_SospMigStats *) USER_NIL) {
  594.         status = GEN_INVALID_ARG;
  595.         } else if (option < sizeof (Fs_SospMigStats)) {
  596.         status = GEN_INVALID_ARG;
  597.         } else {
  598.         status = Vm_CopyOut(sizeof (Fs_SospMigStats),
  599.             (Address) &fs_SospMigStats, argPtr);
  600.         }
  601.         break;
  602.     }
  603.     case SYS_FS_EXTRA_STATS: {
  604.         Fs_NewStats        *statsPtr;
  605.  
  606.         statsPtr = (Fs_NewStats *) argPtr;
  607.         if (statsPtr == (Fs_NewStats *)NIL ||
  608.             statsPtr == (Fs_NewStats *) 0 ||
  609.             statsPtr == (Fs_NewStats *) USER_NIL) {
  610.         status = GEN_INVALID_ARG;
  611.         } else if (option < sizeof (Fs_NewStats)) {
  612.         status = GEN_INVALID_ARG;
  613.         } else {
  614.         status = Vm_CopyOut(sizeof (Fs_NewStats),
  615.             (Address) &fs_MoreStats, argPtr);
  616.         /*
  617.          * This is a hack so that the getcounters program will
  618.          * be able to tell the difference in kernel versions.
  619.          */
  620.         if (status == SUCCESS) {
  621.             status = sizeof (fs_MoreStats);
  622.         }
  623.         }
  624.         break;
  625.     }
  626.  
  627.     case SYS_FSCACHE_EXTRA_STATS: {
  628.         Fscache_ExtraStats    *statsPtr;
  629.  
  630.         statsPtr = (Fscache_ExtraStats *) argPtr;
  631.         if (statsPtr == (Fscache_ExtraStats *)NIL ||
  632.             statsPtr == (Fscache_ExtraStats *) 0 ||
  633.             statsPtr == (Fscache_ExtraStats *) USER_NIL) {
  634.         status = GEN_INVALID_ARG;
  635.         } else if (option < sizeof (Fscache_ExtraStats)) {
  636.         status = GEN_INVALID_ARG;
  637.         } else {
  638.         status = Vm_CopyOut(sizeof (Fscache_ExtraStats),
  639.             (Address) &fscache_ExtraStats, argPtr);
  640.         }
  641.         break;
  642.     }
  643.         case SYS_FS_SOSP_NAME_STATS: {
  644.         Sys_SospNameStats    stats;
  645.  
  646.         if (argPtr == (Address)NIL ||
  647.             argPtr == (Address) 0 ||
  648.             argPtr == (Address) USER_NIL) {
  649.         status = GEN_INVALID_ARG;
  650.         } else if (option < sizeof (Sys_SospNameStats)) {
  651.         status = GEN_INVALID_ARG;
  652.         } else {
  653.         Time timeVal;
  654.         Timer_TicksToTime(totalNameTime,&timeVal);
  655.         stats.totalNameTime = timeVal;
  656.         Timer_TicksToTime(nameTime[1],&timeVal);
  657.         stats.nameTime = timeVal;
  658.         Timer_TicksToTime(nameTime[2],&timeVal);
  659.         stats.prefixTime = timeVal;
  660.         Timer_TicksToTime(nameTime[0],&timeVal);
  661.         stats.miscTime = timeVal;
  662.         stats.numPrefixLookups = SOSPLookupNum;
  663.         stats.numComponents = SOSPLookupComponent;
  664.         stats.numPrefixComponents = SOSPLookupPrefixComponent;
  665.         status = Vm_CopyOut(sizeof (Sys_SospNameStats),
  666.             (Address) &stats, argPtr);
  667.         }
  668.         break;
  669.     }
  670. #endif SOSP91
  671.     case SYS_SCHED_STATS: {
  672.         Sched_Instrument *schedStatPtr;
  673.         Time curTime;
  674.  
  675.         schedStatPtr = (Sched_Instrument *)argPtr;
  676.         if (schedStatPtr == (Sched_Instrument *)NIL ||
  677.         schedStatPtr == (Sched_Instrument *)0 ||
  678.         schedStatPtr == (Sched_Instrument *)USER_NIL) {
  679.         
  680.         Sched_PrintStat();
  681.         } else {
  682.         register int cpu;
  683.         for (cpu = 0; cpu < MACH_MAX_NUM_PROCESSORS; cpu++) {  
  684.             Timer_TicksToTime(sched_Instrument.processor[cpu].
  685.                         noProcessRunning,
  686.                   &sched_Instrument.processor[cpu].idleTime);
  687.         }
  688.         /*
  689.          * If no interrupts received, dev_LastConsoleInput will
  690.          * be 0, so set it to the current time.  This will happen
  691.          * the first time Sched_Stats is called if there were no
  692.          * keyboard interrupts already.
  693.          *
  694.          * Note: dev_LastConsoleInput can't be set during
  695.          * initialization because the timer has not yet been
  696.          * initialized.
  697.          */
  698.         if (dev_LastConsoleInput.seconds == 0) {
  699.             Timer_GetTimeOfDay(&dev_LastConsoleInput,
  700.                        (int *) NIL, (Boolean *) NIL);
  701.         }
  702.         Timer_GetTimeOfDay(&curTime, (int *) NIL, (Boolean *) NIL);
  703.         Time_Subtract(curTime, dev_LastConsoleInput,
  704.                   &sched_Instrument.noUserInput);
  705.         status = Vm_CopyOut(sizeof(Sched_Instrument),
  706.                       (Address)&sched_Instrument, argPtr);
  707.         }
  708.         break;
  709.     }
  710.     case SYS_RPC_CLT_STATS:
  711.     case SYS_RPC_SRV_STATS:
  712.     case SYS_RPC_TRACE_STATS:
  713.     case SYS_RPC_SERVER_HIST:
  714.     case SYS_RPC_CLIENT_HIST:
  715.     case SYS_RPC_SRV_STATE:
  716.     case SYS_RPC_CLT_STATE:
  717.     case SYS_RPC_ENABLE_SERVICE:
  718.     case SYS_RPC_SRV_COUNTS:
  719.     case SYS_RPC_CALL_COUNTS:
  720.     case SYS_RPC_SET_MAX:
  721.     case SYS_RPC_SET_NUM:
  722.     case SYS_RPC_NEG_ACKS:
  723.     case SYS_RPC_CHANNEL_NEG_ACKS:
  724.     case SYS_RPC_NUM_NACK_BUFS:
  725.     case SYS_RPC_SANITY_CHECK:
  726.         status = Rpc_GetStats(command, option, argPtr);
  727.         break;
  728.     case SYS_PROC_MIGRATION: {
  729.         switch(option) {
  730.         /*
  731.          * The first two are for backward compatibility.
  732.          */
  733.         case SYS_PROC_MIG_ALLOW: 
  734.         case SYS_PROC_MIG_REFUSE: {
  735.             register Proc_ControlBlock *procPtr;
  736.             procPtr = Proc_GetEffectiveProc();
  737.             if (procPtr->effectiveUserID != 0) {
  738.             status = GEN_NO_PERMISSION;
  739.             } else {
  740.             /*
  741.              * This part is simplified for now.
  742.              */
  743.             if (option == SYS_PROC_MIG_REFUSE) {
  744.                 proc_AllowMigrationState &= ~PROC_MIG_IMPORT_ALL;
  745.             } else {
  746.                 proc_AllowMigrationState |= PROC_MIG_IMPORT_ALL;
  747.             }
  748.             }
  749.         }
  750.         break;
  751.  
  752.         case SYS_PROC_MIG_SET_STATE: {
  753.             register Proc_ControlBlock *procPtr;
  754.             int arg;
  755.  
  756.             procPtr = Proc_GetEffectiveProc();
  757.             if (procPtr->effectiveUserID != 0) {
  758.             status = GEN_NO_PERMISSION;
  759.             } else {
  760.             status = Vm_CopyIn(sizeof(int), argPtr, (Address)&arg);
  761.             if (status == SUCCESS) {
  762.                 proc_AllowMigrationState = arg;
  763.             }
  764.             }
  765.         }
  766.         break;
  767.  
  768.         /*
  769.          * Also obsolete, here for backward compatibility for a while.
  770.          */
  771.             case SYS_PROC_MIG_GET_STATUS: {
  772.             if (argPtr != (Address) NIL) {
  773.             /*
  774.              * This part is simplified for now.
  775.              */
  776.             int refuse;
  777.             if (proc_AllowMigrationState & PROC_MIG_IMPORT_ALL) {
  778.                 refuse = 0;
  779.             } else {
  780.                 refuse = 1;
  781.             }
  782.             status = Vm_CopyOut(sizeof(Boolean),
  783.                         (Address)&refuse,
  784.                         argPtr);
  785.             } else {
  786.             status = GEN_INVALID_ARG;
  787.             }
  788.         }
  789.         break;
  790.             case SYS_PROC_MIG_GET_STATE: {
  791.             if (argPtr != (Address) NIL) {
  792.             status = Vm_CopyOut(sizeof(Boolean),
  793.                         (Address)&proc_AllowMigrationState,
  794.                         argPtr);
  795.             } else {
  796.             status = GEN_INVALID_ARG;
  797.             }
  798.         }
  799.         break;
  800.             case SYS_PROC_MIG_GET_VERSION: {
  801.             if (argPtr != (Address) NIL) {
  802.             status = Vm_CopyOut(sizeof(int),
  803.                         (Address)&proc_MigrationVersion,
  804.                         argPtr);
  805.             } else {
  806.             status = GEN_INVALID_ARG;
  807.             }
  808.         }
  809.         break;
  810.             case SYS_PROC_MIG_SET_VERSION: {
  811.             register Proc_ControlBlock *procPtr;
  812.             int arg;
  813.  
  814.             procPtr = Proc_GetEffectiveProc();
  815.             if (procPtr->effectiveUserID != 0) {
  816.             status = GEN_NO_PERMISSION;
  817.             } else {
  818.             status = Vm_CopyIn(sizeof(int), argPtr, (Address)&arg);
  819.             if (status == SUCCESS && arg >= 0) {
  820.                 proc_MigrationVersion = arg;
  821.             } else if (status == SUCCESS) {
  822.                 status = GEN_INVALID_ARG;
  823.             }
  824.             }
  825.         }
  826.         break;
  827.         case SYS_PROC_MIG_SET_DEBUG: {
  828.             int arg;
  829.             status = Vm_CopyIn(sizeof(int), argPtr, (Address)&arg);
  830.             if (status == SUCCESS && arg >= 0) {
  831.             proc_MigDebugLevel = arg;
  832.             } else if (status == SUCCESS) {
  833.             status = GEN_INVALID_ARG;
  834.             }
  835.         }
  836.         break;
  837.  
  838.         case SYS_PROC_MIG_GET_STATS: {
  839.             status = Proc_MigGetStats(argPtr);
  840.             break;
  841.         }
  842.         case SYS_PROC_MIG_RESET_STATS: {
  843.             status = Proc_MigResetStats();
  844.             break;
  845.         }
  846.         default:{
  847.             status = GEN_INVALID_ARG;
  848.         }
  849.         break;
  850.         }
  851.         break;
  852.     }
  853.     
  854.     case SYS_PROC_TRACE_STATS: {
  855.         switch(option) {
  856.         case SYS_PROC_TRACING_PRINT:
  857.             printf("%s %s\n", "Warning:",
  858.                 "Printing of proc trace records not implemented.");
  859.             break;
  860.         case SYS_PROC_TRACING_ON:
  861.             Proc_MigrateStartTracing();
  862.             break;
  863.         case SYS_PROC_TRACING_OFF:
  864.             proc_DoTrace = FALSE;
  865.             break;
  866.         default:
  867.             /*
  868.              * The default is to copy 'option' trace records.
  869.              */
  870.             status = Trace_Dump(proc_TraceHdrPtr, option, argPtr);
  871.             break;
  872.         }
  873.         break;
  874.     }
  875.     case SYS_FS_PREFIX_STATS: {
  876.         status = Fsprefix_Dump(option, argPtr);
  877.         break;
  878.     }
  879.     case SYS_FS_PREFIX_EXPORT: {
  880.         status = Fsprefix_DumpExport(option, argPtr);
  881.         break;
  882.     }
  883.     case SYS_SYS_CALL_STATS: {
  884.         status = Sys_OutputNumCalls(option, argPtr);
  885.         break;
  886.     }
  887.     case SYS_NET_GET_ROUTE: {
  888.         status = Net_IDToRouteStub(option, sizeof(Net_RouteInfo), argPtr);
  889.         break;
  890.     }
  891.     case SYS_NET_ETHER_STATS: {
  892.         Net_Stats    stats;
  893.         status = Net_GetStats(NET_NETWORK_ETHER, &stats);
  894.         status = Vm_CopyOut(sizeof(Net_EtherStats),
  895.                 (Address)&stats.ether, (Address)argPtr);
  896.         break;
  897.     }
  898.     case SYS_DISK_STATS: {
  899.         int            count;
  900.         Sys_DiskStats    *statArrPtr;
  901.  
  902.         if ((option < 0) || (option > 10000)) {
  903.         status = GEN_INVALID_ARG;
  904.         } else { 
  905.         statArrPtr = (Sys_DiskStats *)
  906.                     malloc(sizeof(Sys_DiskStats) * option);
  907.         count = Dev_GetDiskStats(statArrPtr, option);
  908.         status = Vm_CopyOut(sizeof(Sys_DiskStats) * count, 
  909.                     (Address)statArrPtr, (Address)argPtr);
  910.         free((Address) statArrPtr);
  911.         }
  912.         break;
  913.     }
  914.     case SYS_LOCK_STATS: {
  915.         status = Sync_GetLockStats(option, argPtr);
  916.         break;
  917.     }
  918.     case SYS_LOCK_RESET_STATS: {
  919.         status = Sync_ResetLockStats();
  920.         break;
  921.     }
  922.     case SYS_INST_COUNTS: {
  923. #ifdef spur
  924.         Mach_InstCountInfo    info[MACH_MAX_INST_COUNT];
  925.         Mach_GetInstCountInfo(info);
  926.         Vm_CopyOut(sizeof(info), (Address) info, 
  927.         argPtr);
  928.         status = SUCCESS;
  929. #else
  930.         status = GEN_NOT_IMPLEMENTED;
  931. #endif
  932.         break;
  933.     }
  934.     case SYS_RESET_INST_COUNTS: {
  935. #ifdef spur
  936.         bzero(mach_InstCount, sizeof(mach_InstCount));
  937.         status = SUCCESS;
  938. #else
  939.         status = GEN_NOT_IMPLEMENTED;
  940. #endif
  941.         break;
  942.     }
  943.     case SYS_RECOV_STATS: {
  944.         status = Recov_GetStats(option, argPtr);
  945.         break;
  946.     }
  947.     case SYS_RECOV_PRINT: {
  948.         Recov_ChangePrintLevel(option);
  949.         status = SUCCESS;
  950.         break;
  951.     }
  952.     case SYS_RECOV_ABS_PINGS: {
  953.         recov_AbsoluteIntervals = option;
  954.         status = SUCCESS;
  955.         break;
  956.     }
  957.     case SYS_FS_RECOV_INFO: {
  958.         int        length;
  959.         Address    resultPtr;
  960.         int        lengthNeeded;
  961.  
  962.         resultPtr = argPtr;
  963.         /* option is actually an in/out param */
  964.         status = Vm_CopyIn(sizeof (int), (Address) option,
  965.             (Address) &length);
  966.         if (status != SUCCESS) {
  967.         break;
  968.         }
  969.         if (length != 0 && (resultPtr == (Address) NIL || resultPtr ==
  970.             (Address) 0 || resultPtr == (Address) USER_NIL)) {
  971.         status = GEN_INVALID_ARG;
  972.         break;
  973.         }
  974.         if (length > 0) {
  975.         resultPtr = (Address) malloc(length);
  976.         } else {
  977.         resultPtr = (Address) NIL;
  978.         }
  979.         status = Fsutil_FsRecovInfo(length,
  980.             (Fsutil_FsRecovNamedStats *) resultPtr, &lengthNeeded);
  981.         if (status != SUCCESS) {
  982.         if (resultPtr != (Address) NIL) {
  983.             free(resultPtr);
  984.         }
  985.         break;
  986.         }
  987.         status = Vm_CopyOut(length, resultPtr, argPtr);
  988.         if (status != SUCCESS) {
  989.         if (resultPtr != (Address) NIL) {
  990.             free(resultPtr);
  991.         }
  992.         break;
  993.         }
  994.         status = Vm_CopyOut(sizeof (int), (Address) &lengthNeeded,
  995.             (Address) option);
  996.         if (resultPtr != (Address) NIL) {
  997.         free(resultPtr);
  998.         }
  999.         break;
  1000.     }
  1001.     case SYS_RECOV_CLIENT_INFO: {
  1002.         int        length;
  1003.         Address    resultPtr;
  1004.         int        lengthNeeded;
  1005.  
  1006.         resultPtr = argPtr;
  1007.         /* option is actually an in/out param */
  1008.         status = Vm_CopyIn(sizeof (int), (Address) option,
  1009.             (Address) &length);
  1010.         if (status != SUCCESS) {
  1011.         break;
  1012.         }
  1013.         if (length != 0 && (resultPtr == (Address) NIL || resultPtr ==
  1014.             (Address) 0 || resultPtr == (Address) USER_NIL)) {
  1015.         status = GEN_INVALID_ARG;
  1016.         break;
  1017.         }
  1018.         if (length > 0) {
  1019.         resultPtr = (Address) malloc(length);
  1020.         } else {
  1021.         resultPtr = (Address) NIL;
  1022.         }
  1023.         status = Recov_DumpClientRecovInfo(length, resultPtr,
  1024.             &lengthNeeded);
  1025.         if (status != SUCCESS) {
  1026.         if (resultPtr != (Address) NIL) {
  1027.             free(resultPtr);
  1028.         }
  1029.         break;
  1030.         }
  1031.         status = Vm_CopyOut(length, resultPtr, argPtr);
  1032.         if (status != SUCCESS) {
  1033.         if (resultPtr != (Address) NIL) {
  1034.             free(resultPtr);
  1035.         }
  1036.         break;
  1037.         }
  1038.         status = Vm_CopyOut(sizeof (int), (Address) &lengthNeeded,
  1039.             (Address) option);
  1040.         if (resultPtr != (Address) NIL) {
  1041.         free(resultPtr);
  1042.         }
  1043.         break;
  1044.     }
  1045.     case SYS_RPC_SERVER_TRACE:
  1046.         if (option == TRUE) {
  1047.         Rpc_OkayToTrace(TRUE);
  1048.         } else  {
  1049.         Rpc_OkayToTrace(FALSE);
  1050.         }
  1051.         status = SUCCESS;
  1052.         
  1053.         break;
  1054.     case SYS_RPC_SERVER_FREE:
  1055.         Rpc_FreeTraces();
  1056.         status = SUCCESS;
  1057.  
  1058.         break;
  1059.     case SYS_RPC_SERVER_INFO: {
  1060.         int        length;
  1061.         Address    resultPtr;
  1062.         int        lengthNeeded;
  1063.  
  1064.         resultPtr = argPtr;
  1065.         /* option is actually an in/out param */
  1066.         status = Vm_CopyIn(sizeof (int), (Address) option,
  1067.             (Address) &length);
  1068.         if (status != SUCCESS) {
  1069.         break;
  1070.         }
  1071.         if (length != 0 && (resultPtr == (Address) NIL || resultPtr ==
  1072.             (Address) 0 || resultPtr == (Address) USER_NIL)) {
  1073.         status = GEN_INVALID_ARG;
  1074.         break;
  1075.         }
  1076.         if (length > 0) {
  1077.         resultPtr = (Address) malloc(length);
  1078.         } else {
  1079.         resultPtr = (Address) NIL;
  1080.         }
  1081.         status = Rpc_DumpServerTraces(length,
  1082.             (RpcServerUserStateInfo *)resultPtr, &lengthNeeded);
  1083.         if (status != SUCCESS) {
  1084.         if (resultPtr != (Address) NIL) {
  1085.             free(resultPtr);
  1086.         }
  1087.         break;
  1088.         }
  1089.         status = Vm_CopyOut(length, resultPtr, argPtr);
  1090.         if (status != SUCCESS) {
  1091.         if (resultPtr != (Address) NIL) {
  1092.             free(resultPtr);
  1093.         }
  1094.         break;
  1095.         }
  1096.         status = Vm_CopyOut(sizeof (int), (Address) &lengthNeeded,
  1097.             (Address) option);
  1098.         if (resultPtr != (Address) NIL) {
  1099.         free(resultPtr);
  1100.         }
  1101.         break;
  1102.     }
  1103.     case SYS_START_STATS: {
  1104.         /* schedule the stuff */
  1105.         Dev_StartIOStats();
  1106.         Sched_StartSchedStats();
  1107.         status = SUCCESS;
  1108.         break;
  1109.     }
  1110.     case SYS_END_STATS: {
  1111.         /* deschedule the stuff */
  1112.         Dev_StopIOStats();
  1113.         Sched_StopSchedStats();
  1114.         status = SUCCESS;
  1115.         break;
  1116.     }
  1117. #ifdef SOSP91
  1118.     case SYS_TRACELOG_STATS: { /* Tracing for SOSP91 */
  1119.         if (option == SYS_TRACELOG_ON) {
  1120.         int args[2]; /* NumBuffers, BufSize */
  1121.         status = Vm_CopyIn(2*sizeof (int), (Address) argPtr,
  1122.             (Address)args);
  1123.         if (status != SUCCESS) {
  1124.             break;
  1125.         }
  1126.         if (SOSP91TracePtr == NULL) {
  1127.             SOSP91TracePtr = (TraceLog_Header *)
  1128.                 malloc(sizeof(TraceLog_Header));
  1129.             if (args[0]<0) {
  1130.             /*
  1131.              * Negative # of buffers is the magic indicator
  1132.              * that we don't want to buffer data.
  1133.              */
  1134.             TraceLog_Init(SOSP91TracePtr, -args[0], args[1],
  1135.                 TRACELOG_NO_BUF, VERSIONLETTER);
  1136.             } else {
  1137.             TraceLog_Init(SOSP91TracePtr, args[0], args[1], 0,
  1138.                 VERSIONLETTER);
  1139.             }
  1140.         }
  1141.         traceLog_Disable = FALSE;
  1142.         } else if (option == SYS_TRACELOG_OFF) {
  1143.         TraceLog_Header *tmpPtr;
  1144.         tmpPtr = SOSP91TracePtr;
  1145.         SOSP91TracePtr = NULL;
  1146.         TraceLog_Finish(tmpPtr);
  1147.         traceLog_Disable = TRUE;
  1148.         } else if (option == SYS_TRACELOG_RESET) {
  1149.         if (SOSP91TracePtr != NULL) {
  1150.             TraceLog_Reset(SOSP91TracePtr);
  1151.         }
  1152.         } else if (option == SYS_TRACELOG_DUMP) {
  1153.         TraceLog_Dump(SOSP91TracePtr, argPtr+
  1154.             sizeof(Sys_TracelogHeaderKern), argPtr);
  1155.         }
  1156.         status = SUCCESS;
  1157.         break;
  1158.     }
  1159. #endif
  1160. #ifdef sun4c
  1161.         case SYS_DEV_CHANGE_SCSI_DEBUG: {
  1162.         Dev_ChangeScsiDebugLevel(option);
  1163.         status = SUCCESS;
  1164.         break;
  1165.     }
  1166. #endif sun4c
  1167.     default:
  1168.         status = GEN_INVALID_ARG;
  1169.         break;
  1170.     }
  1171.     return(status);
  1172. }
  1173.